﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Luna.Extender;
using System.Windows.Forms;
using System.Reflection;
using System.Collections;
using System.ComponentModel;

namespace Luna
{
	public static class ExtensionManagerExtension
	{
		public static void invokeFormExtention(this IExtensionManager manager, IAppContext context, Form form, string point) {
			Type formExtType = typeof(IFormExtension);
			IAppContext formContext = form.getPropertyValue<IAppContext>("Context", null).getDefaultValue(context);

			foreach (IExtensionItem item in manager.getExtensionItems(form.Name + point))
				if (item.Type != null && formExtType.IsAssignableFrom(item.Type)) {
					IFormExtension ext = (IFormExtension)item.createExtension(formContext);
					ext.extent(formContext, form, item);
				}
		}

		public static void invokeFormCreationExtension(this IExtensionManager manager, IAppContext context, Form form) {
			invokeFormExtention(manager, context, form, ".OnCreate");
		}

		enum PropertyAction { Set, AddSubItem };

		public static object createExtensionFromItem(this IExtensionItem item, IAppContext context) {
			object ext = null;
			if (item.Type != null) {
				ConstructorInfo ctor = item.Type.GetConstructor(new Type[] { typeof(IAppContext) });
				if (ctor != null)
					ext = ctor.Invoke(new object[] { context });
				else {
					ext = Activator.CreateInstance(item.Type);
					ext.setPropertyValue("Context", context, null);
				}
				if (ext != null) {
					foreach(IExtensionItem child in item.Children)
						if (child.Name.Equals("property")) {
							PropertyInfo prop = ext.getMember<PropertyInfo>(child["name"], false);
							
							if (prop != null) {
								PropertyAction act = (PropertyAction)Enum.Parse(typeof(PropertyAction), child["action"].getDefaultValue("Set"));
								object value = null;
								switch (act) {
									case PropertyAction.Set:
										if (prop.PropertyType.IsClass && prop.PropertyType != typeof(string))
											value = createExtensionFromItem(child, context);
										else
											value = child["value"].convertTo(prop.PropertyType);
										prop.SetValue(ext, value, null);
										break;
									case PropertyAction.AddSubItem:
										object propValue = prop.GetValue(ext, null);
										bool isList = propValue is IList;
										bool isDict = propValue is IDictionary;
										foreach (IExtensionItem subchild in child.Children)
											if (subchild.Name.Equals("add")) {
												Type subchildType = subchild.Type != null ? subchild.Type : typeof(string);
												if (subchildType.IsValueType || TypeDescriptor.GetConverter(subchildType).CanConvertFrom(typeof(string)))
													value = subchild["value"].convertTo(subchildType);
												else
													value = createExtensionFromItem(subchild, context);
													
												if (isList)
													(propValue as IList).Add(value);
												else if (isDict)
													(propValue as IDictionary)[subchild["name"]] = value;
											}
										break;
									default:
										break;
								}
							}
						}
				}
			}
			return ext;
		}
	}
}
